
// panel object
local PANEL = { };


/*------------------------------------
	initialize the playlist manager
------------------------------------*/
function PANEL:Init( )

	// set the dialog title
	self:SetTitle( "#musex_plmanager_title" );
	
	// create the filename label
	self.FilenameLabel = vgui.Create( "MXLabel", self );
	// set the text
	self.FilenameLabel:SetText( "#musex_plmanager_filename" );
	
	// create the filename text entry
	self.FilenameEntry = vgui.Create( "MXTextEntry", self );
	// make it editable
	self.FilenameEntry:SetEditable( true );
	// check for valid entry
	self.FilenameEntry.AllowInput = function( self, str )
	
		// list of bad characters
		local blacklist = { "\\", "/", "*", "?", "\"", "<", ">", "|", "." };
		
		// return boolean
		return ( table.HasValue( blacklist, str ) );
	
	end
	// do file matching for them
	self.FilenameEntry.OnValueChange = function( self, str )
	
		// TODO
		
	end
	
	// create the save button
	self.SaveFile = vgui.Create( "MXButton", self );
	// set the text
	self.SaveFile:SetText( "#musex_plmanager_save" );
	// setup the click function
	self.SaveFile.DoClick = function( self )
	
		// call the save playlist function
		self.GetParent( self ):SavePlaylist();
		
	end
	
	// create the file lists
	self.List = vgui.Create( "MXComboBox", self );
	
	// create the done button
	self.Done = vgui.Create( "MXButton", self );
	// set the text
	self.Done:SetText( "#musex_done" );
	// setup the done function
	self.Done.DoClick = function( self )
		
		// close the manager
		self.GetParent( self ):Close();
		
	end
	
	// create the delete button
	self.Delete = vgui.Create( "MXButton", self );
	// set the text
	self.Delete:SetText( "#musex_plmanager_delete" );
	// setup the delete function
	self.Delete.DoClick = function( self )
	
		// call the delete playlist function
		self.GetParent( self ):DeletePlaylist();
		
	end
	
	// create the load button
	self.Load = vgui.Create( "MXButton", self );
	// set the text
	self.Load:SetText( "#musex_plmanager_load" );
	// setup the load function
	self.Load.DoClick = function( self )
	
		// call the load playlist function
		self.GetParent( self ):LoadPlaylist();
		
	end
	
	// create the question label
	self.QuestionLabel = vgui.Create( "MXLabel", self );
	// set the default text
	self.QuestionLabel:SetText( "???" );
	
	// create the question yes button
	self.QuestionYes = vgui.Create( "MXButton", self );
	// set the text
	self.QuestionYes:SetText( "#musex_plmanager_yes" );
	// setup the yes function
	self.QuestionYes.DoClick = function( self )
	
		// call the answer function
		self.GetParent( self ):AnswerQuestion( "yes" );
		
	end
	
	// create the question no button
	self.QuestionNo = vgui.Create( "MXButton", self );
	// set the text
	self.QuestionNo:SetText( "#musex_plmanager_no" );
	// setup the no function
	self.QuestionNo.DoClick = function( self )
	
		// call the answer function
		self.GetParent( self ):AnswerQuestion( "no" );
		
	end

	// custom derma hooks
	Derma_Hook( self, "Paint", "Paint", "MXMainFrame" );
	Derma_Hook( self, "ApplySchemeSettings", "Scheme", "MXFrame" );
	self.AnimIn = Derma_Anim( "OpenAnim", self, self.OpenAnim );
	self.AnimOut = Derma_Anim( "CloseAnim", self, self.CloseAnim );

end


/*------------------------------------
	open the manager
------------------------------------*/
function PANEL:Open( )

	// ignore if we're already visible
	if ( self:IsVisible() ) then
	
		// bye
		return;
		
	end
	
	// setup the control visibility
	self:SetControlsVisible( true );
	
	// close menus
	CloseDermaMenus();
	
	// take focus and be visible
	self:MakePopup();
	self:SetVisible( true );
	self:DoModal();
	
	// enable keyboard input
	self:SetKeyboardInputEnabled( true );
	
	// enable mouse input
	self:SetMouseInputEnabled( true );
	
	// halt the close animation
	self.AnimOut:Stop();
	
	// start the open animation
	self.AnimIn:Start( 0.1 );

end


/*------------------------------------
	handle the opening animation
------------------------------------*/
function PANEL:OpenAnim( anim, delta, data )

	// check if it has been started
	if ( anim.Started ) then
	
		// reset alpha
		self:SetAlpha( 0 );
		
	end
	
	// check if it has been finished
	if ( anim.Finished ) then
	
		// fully opaque
		self:SetAlpha( 255 );
		
		// list files
		self:ListFiles();
		
		// all done
		return;
		
	end
	
	// animate the alpha
	self:SetAlpha( 255 * delta );

end


/*------------------------------------
	close the manager
------------------------------------*/
function PANEL:Close( skip )
	
	// close menus
	CloseDermaMenus();
	
	// clear the text
	self.FilenameEntry:SetText( "" );
	
	// halt the opening animation
	self.AnimIn:Stop();
	
	// check if we're skipping the animation
	if ( skip ) then
	
		// restore alpha
		self:SetAlpha( 255 );
		
		// not visible
		self:SetVisible( false );
	
	else
	
		// start the close animation
		self.AnimOut:Start( 0.1 );
		
	end

end


/*------------------------------------
	handle the closing animation
------------------------------------*/
function PANEL:CloseAnim( anim, delta, data )

	// check if the animation has started
	if ( anim.Started ) then
	
		// restore the alpha
		self:SetAlpha( 255 );
		
	end
	
	// check if the animation has finished
	if ( anim.Finished ) then
	
		// store alpha
		self:SetAlpha( 255 );
		
		// set as not visible
		self:SetVisible( false );
		
		// destroy
		self:Remove();
		
		// all done
		return;
		
	end
	
	// animate the alpha
	self:SetAlpha( 255 - 255 * delta );

end


/*------------------------------------
	layout the manager
------------------------------------*/
function PANEL:PerformLayout( )

	// BaseClass stuff
	self.BaseClass.PerformLayout( self );
	
	// size & position filename label
	self.FilenameLabel:SetPos( 7, 30 );
	self.FilenameLabel:SizeToContents();
	
	// size & position filename text entry
	self.FilenameEntry:SetPos( 5, self.FilenameLabel.Y + self.FilenameLabel:GetTall() + 5 );
	self.FilenameEntry:SetSize( self:GetWide() - 90, 20 );
	
	self.SaveFile:SetPos( self.FilenameEntry.X + self.FilenameEntry:GetWide() + 5, self.FilenameEntry.Y );
	self.SaveFile:SetSize( 75, 20 );
	
	// size & position file list
	self.List:SetPos( 5, self.FilenameEntry.Y + self.FilenameEntry:GetTall() + 5 );
	self.List:SetSize( self:GetWide() - 10, self:GetTall() - ( self.List.Y + 30 ) );
	
	// size & position load button
	self.Load:SetSize( 75, 20 );
	self.Load:SetPos( 5, self:GetTall() - 25 );
	
	// size & position delete button
	self.Delete:SetSize( 75, 20 );
	self.Delete:SetPos( 85, self:GetTall() - 25 );
	
	// size & position done button
	self.Done:SetSize( 75, 20 );
	self.Done:SetPos( self:GetWide() - 80, self:GetTall() - 25 );
	
	// position the question label
	self.QuestionLabel:SetPos( 10, 50 );
	
	// size & position the question yes
	self.QuestionYes:SetSize( 75, 20 );
	self.QuestionYes:SetPos( ( self:GetWide() * 0.5 ) - 100, 150 );
	
	// size & position the question no
	self.QuestionNo:SetSize( 75, 20 );
	self.QuestionNo:SetPos( ( self:GetWide() * 0.5 ) + 25, 150 );
	
end


/*------------------------------------
	manager think
------------------------------------*/
function PANEL:Think( )

	// call BaseClass
	self.BaseClass.Think( self );
	
	// check if they finishing moving the window
	if ( !self.Dragging && self.WasDragging ) then
	
		// update position in settings
		MuseX.SetSetting( "managerx", self.X );
		MuseX.SetSetting( "managery", self.Y );
		
	end
	
	// update previous dragging state
	self.WasDragging = self.Dragging;
	
	// run the animation functions
	self.AnimIn:Run();
	self.AnimOut:Run();

end


/* CUSTOM PANEL FUNCTIONS */


/*------------------------------------
	ask a question to user
------------------------------------*/
function PANEL:AskQuestion( text, func )

	// store the function
	self.QuestionFunc = func;
	
	// set the text
	self.QuestionLabel:SetText( text );

	// size & position the question label
	self.QuestionLabel:SizeToContents();
	self.QuestionLabel:SetPos( ( self:GetWide() * 0.5 ) - ( self.QuestionLabel:GetWide() * 0.5 ), 50 );
	
	// toggle the controls
	self:SetControlsVisible( false );
	
end


/*------------------------------------
	question has been answered
------------------------------------*/
function PANEL:AnswerQuestion( answer )

	// check if they answered yes
	if ( answer == "yes" ) then
	
		// call the function
		self.QuestionFunc();
	
	end
	
	// clear the function
	self.QuestionFunc = nil;
	
	// toggle the controls
	self:SetControlsVisible( true );
	
end


/*------------------------------------
	change control visibility
------------------------------------*/
function PANEL:SetControlsVisible( bool )

	// non-question controls
	self.FilenameLabel:SetVisible( bool );
	self.FilenameEntry:SetVisible( bool );
	self.SaveFile:SetVisible( bool );
	self.List:SetVisible( bool );
	self.Load:SetVisible( bool );
	self.Delete:SetVisible( bool );
	self.Done:SetVisible( bool );
	
	// question controls
	self.QuestionLabel:SetVisible( !bool );
	self.QuestionYes:SetVisible( !bool );
	self.QuestionNo:SetVisible( !bool );

end


/*------------------------------------
	list playlist files
------------------------------------*/
function PANEL:ListFiles( )

	// clear current files
	self.List:Clear();
	
	// find all playlists
	local files = file.Find( "musex/playlists/*.txt" );
	
	// loop through the list
	for _, f in pairs( files ) do
	
		// remove the .txt extension
		local name = f:sub( 1, #f - 4 );
		
		// make sure its not the "nowplaying" list
		if ( name != "nowplaying" ) then
	
			// add file to list
			local item = self.List:AddItem( name );
			
			// store the filename
			item.Filename = name;
			
			// store the dialog
			item.Manager = self;
			
			// setup the click function
			item.DoClick = function( self )
			
				// get the text entry
				local entry = item.Manager.FilenameEntry;
				
				// set the text
				entry:SetText( self.Filename );
			
			end
			
		end
	
	end
	
end


/*------------------------------------
	save the playlist
------------------------------------*/
function PANEL:SavePlaylist( overwrite )

	// get the file name
	local name = self.FilenameEntry:GetValue();
	
	// make sure its not empty
	if ( name == "" ) then
	
		// why are you so stupid?
		return;
		
	end

	// build full file path & name
	local fullfile = ("musex/playlists/%s.txt"):format( name );
	
	// check if it exists
	if ( file.Exists( fullfile ) && !overwrite ) then
	
		// build the funciton
		local func = function()
		
			self:SavePlaylist( true );
			
		end
	
		// ask the question
		self:AskQuestion( "#musex_plmanager_confirmoverwrite", func );
		
		return;
	
	end
	
	// save the playlist
	MuseX.SavePlaylist( name, MuseX.GetPlaylist() );
	
	// call the close function
	self.Done:DoClick();
	
end


/*------------------------------------
	load a playlist
------------------------------------*/
function PANEL:LoadPlaylist( )

	// get the selected item in list
	local selected = self.List:GetSelected();
	
	// make sure they selected something
	if ( !selected ) then
	
		// nope, leave
		return;
		
	end
	
	// load the playlist
	MuseX.LoadPlaylist( selected.Filename or "" );
	
	// call the close function
	self.Done:DoClick();

end


/*------------------------------------
	delete a playlist
------------------------------------*/
function PANEL:DeletePlaylist( delete )

	// get the selected item
	local selected = self.List:GetSelected();
	
	// make sure they have something selected
	if ( !selected ) then
	
		// nope, leave
		return;
		
	end
	
	// build full file path & name
	local fullfile = ("musex/playlists/%s.txt"):format( selected.Filename );
	
	// make sure it exists
	if ( !file.Exists( fullfile ) ) then
	
		// doesn't exist
		return;
	
	end
	
	// make sure they confirmed it
	if ( !delete ) then
	
		// build the funciton
		local func = function()
		
			self:DeletePlaylist( true );
			
		end
	
		// ask the question
		self:AskQuestion( "#musex_plmanager_confirmdelete", func );
		
		return;
	
	end
	
	// delete the file
	file.Delete( fullfile );
	
	// clear the text
	self.FilenameEntry:SetText( "" );
	
	// refresh listing
	self:ListFiles();

end

// define
derma.DefineControl( "MXPlaylistManager", "", PANEL, "DFrame" );
